1   /*
2    * Copyright 2016-2020 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      https://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.springframework.integration.jpa.dsl;
18  
19  import org.springframework.expression.Expression;
20  import org.springframework.integration.expression.ValueExpression;
21  import org.springframework.integration.jpa.core.JpaExecutor;
22  import org.springframework.integration.jpa.support.OutboundGatewayType;
23  
24  /**
25   * A {@link JpaBaseOutboundEndpointSpec} extension for the
26   * {@link org.springframework.integration.jpa.outbound.JpaOutboundGateway} with
27   * {@link org.springframework.integration.jpa.support.OutboundGatewayType#RETRIEVING} mode.
28   *
29   * @author Artem Bilan
30   *
31   * @since 5.0
32   */
33  public class JpaRetrievingOutboundGatewaySpec extends JpaBaseOutboundEndpointSpec<JpaRetrievingOutboundGatewaySpec> {
34  
35  	protected JpaRetrievingOutboundGatewaySpec(JpaExecutor jpaExecutor) {
36  		super(jpaExecutor);
37  		this.target.setGatewayType(OutboundGatewayType.RETRIEVING);
38  		this.target.setRequiresReply(true);
39  	}
40  
41  	/**
42  	 * This parameter indicates that only one result object shall be returned as
43  	 * a result from the executed JPA operation. If set to <code>true</code> and
44  	 * the result list from the JPA operations contains only 1 element, then that
45  	 * 1 element is extracted and returned as payload.
46  	 * @param expectSingleResult true if a single object is expected.
47  	 * @return the spec
48  	 */
49  	public JpaRetrievingOutboundGatewaySpec expectSingleResult(boolean expectSingleResult) {
50  		this.jpaExecutor.setExpectSingleResult(expectSingleResult);
51  		return this;
52  	}
53  
54  	/**
55  	 * Specify a first result in the query executed.
56  	 * @param firstResult the first result to use.
57  	 * @return the spec
58  	 */
59  	public JpaRetrievingOutboundGatewaySpec firstResult(int firstResult) {
60  		return firstResultExpression(new ValueExpression<>(firstResult));
61  	}
62  
63  	/**
64  	 * Specify a SpEL expression that will be evaluated to get the first result in the query executed.
65  	 * @param firstResultExpression The first result expression.
66  	 * @return the spec
67  	 */
68  	public JpaRetrievingOutboundGatewaySpec firstResultExpression(String firstResultExpression) {
69  		return firstResultExpression(PARSER.parseExpression(firstResultExpression));
70  	}
71  
72  	/**
73  	 * Specify a SpEL expression that will be evaluated to get the first result in the query executed.
74  	 * @param firstResultExpression The first result expression.
75  	 * @return the spec
76  	 */
77  	public JpaRetrievingOutboundGatewaySpec firstResultExpression(Expression firstResultExpression) {
78  		this.jpaExecutor.setFirstResultExpression(firstResultExpression);
79  		return this;
80  	}
81  
82  	/**
83  	 * Specify a SpEL expression that will be evaluated to get the {@code primaryKey} for
84  	 * {@link javax.persistence.EntityManager#find(Class, Object)}
85  	 * @param idExpression the SpEL expression for entity {@code primaryKey}.
86  	 * @return the spec
87  	 */
88  	public JpaRetrievingOutboundGatewaySpec idExpression(String idExpression) {
89  		return idExpression(PARSER.parseExpression(idExpression));
90  	}
91  
92  	/**
93  	 * Specify a SpEL expression that will be evaluated to get the {@code primaryKey} for
94  	 * {@link javax.persistence.EntityManager#find(Class, Object)}
95  	 * @param idExpression the SpEL expression for entity {@code primaryKey}.
96  	 * @return the spec
97  	 */
98  	public JpaRetrievingOutboundGatewaySpec idExpression(Expression idExpression) {
99  		this.jpaExecutor.setIdExpression(idExpression);
100 		return this;
101 	}
102 
103 	/**
104 	 * Set the maximum number of results expression. It has be a non null value
105 	 * Not setting one will default to the behavior of fetching all the records
106 	 * @param maxResults the maximum number of results to retrieve
107 	 * @return the spec
108 	 */
109 	public JpaRetrievingOutboundGatewaySpec maxResults(int maxResults) {
110 		return maxResultsExpression(new ValueExpression<>(maxResults));
111 	}
112 
113 	/**
114 	 * Specify a SpEL expression for maximum number of results expression.
115 	 * Not setting one will default to the behavior of fetching all the records
116 	 * @param maxResultsExpression The maximum results expression.
117 	 * @return the spec
118 	 */
119 	public JpaRetrievingOutboundGatewaySpec maxResultsExpression(String maxResultsExpression) {
120 		return maxResultsExpression(PARSER.parseExpression(maxResultsExpression));
121 	}
122 
123 	/**
124 	 * Specify a SpEL expression for maximum number of results expression.
125 	 * Not setting one will default to the behavior of fetching all the records
126 	 * @param maxResultsExpression The maximum results expression.
127 	 * @return the spec
128 	 */
129 	public JpaRetrievingOutboundGatewaySpec maxResultsExpression(Expression maxResultsExpression) {
130 		this.jpaExecutor.setMaxResultsExpression(maxResultsExpression);
131 		return this;
132 	}
133 
134 	/**
135 	 * If set to {@code true}, the retrieved objects are deleted from the database upon
136 	 * being polled. May not work in all situations, e.g. for Native SQL Queries.
137 	 * @param deleteAfterPoll defaults to {@code false}.
138 	 * @return the spec
139 	 */
140 	public JpaRetrievingOutboundGatewaySpec deleteAfterPoll(boolean deleteAfterPoll) {
141 		this.jpaExecutor.setDeleteAfterPoll(deleteAfterPoll);
142 		return this;
143 	}
144 
145 	/**
146 	 * If not set, this property defaults to <code>false</code>, which means that
147 	 * deletion occurs on a per object basis if a collection of entities is being
148 	 * deleted.
149 	 *<p>If set to 'true' the elements of the payload are deleted as a batch
150 	 * operation. Be aware that this exhibits issues in regards to cascaded deletes.
151 	 *<p>The specification 'JSR 317: Java Persistence API, Version 2.0' does not
152 	 * support cascaded deletes in batch operations. The specification states in
153 	 * chapter 4.10:
154 	 *<p>"A delete operation only applies to entities of the specified class and
155 	 * its subclasses. It does not cascade to related entities."
156 	 * @param deleteInBatch Defaults to 'false' if not set.
157 	 * @return the spec
158 	 */
159 	public JpaRetrievingOutboundGatewaySpec deleteInBatch(boolean deleteInBatch) {
160 		this.jpaExecutor.setDeleteInBatch(deleteInBatch);
161 		return this;
162 	}
163 
164 	/**
165 	 * If set to {@code true} the {@link javax.persistence.EntityManager#flush()} will be called
166 	 * after persistence operation.
167 	 * Has the same effect, if the {@code flushSize} is specified to {@code 1}.
168 	 * For convenience in cases when the provided entity to persist is not an instance of {@link Iterable}.
169 	 * @param flush defaults to 'false'.
170 	 * @return the spec
171 	 */
172 	public JpaRetrievingOutboundGatewaySpec flushAfterDelete(boolean flush) {
173 		this.jpaExecutor.setFlush(flush);
174 		return this;
175 	}
176 
177 }